package cn.dm.example.lock;

import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

@Slf4j
public class LockExample3 {

    private final Map<String, Data> map = new TreeMap<>();

    // 使用 ReentrantReadWriteLock 锁
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    private final Lock readLock = lock.readLock();

    private final Lock writeLock = lock.writeLock();

    /**
     * 下面提供三个方法
     * 根据key获取数据、获取所有key 和 更新数据
     * (思路:先加读锁/写锁,然后进行操作,最后在 finally 代码块中释放)
     */
    public Data get(String key) {
        readLock.lock();
        try {
            return map.get(key);
        } finally {
            readLock.unlock();
        }
    }

    public Set<String> getAllKeys() {
        readLock.lock();
        try {
            return map.keySet();
        } finally {
            readLock.unlock();
        }
    }

    public Data put(String key, Data value) {
        /**
         * 注:在没有任何读写锁的时候，才能进行写入操作
         * 即获取写入锁时,不允许有任何的读锁还保持着!!!
         *
         * 因此该锁(即ReentrantReadWriteLock)适用于读多写少的场景
         */
        writeLock.lock();
        try {
            return map.put(key, value);
        } finally {
            readLock.unlock();
        }
    }

    class Data {
    }
}
